using System;
using Crainiate.Data.Persistence.Providers;

namespace Crainiate.Data.Persistence.Modelling.Entities
{
    [Serializable]
    public abstract class Entity: IPersistable
    {
        //Property variables
        [NonSerialized] Context _context;
        [NonSerialized] Command _command;
        private Concurrency _concurrency;

        #region Interface

        //Constructors
        public Entity()
        {
        }

        public Entity(Context context)
        {
            Context = context;
        }

        //Properties
        public virtual Context Context
        {
            get
            {
                return _context;
            }
            set
            {
                _context = value;
                _command = null;
                _concurrency = null;
            }
        }

        public virtual Command Command
        {
            get
            {
                return _command;
            }
            set
            {
                _command = value;
            }
        }

        public virtual Concurrency Concurrency
        {
            get
            {
                return _concurrency;
            }
            set
            {
                _concurrency = value;
            }
        }

        //Methods
        public virtual void Update()
        {
            if (Context == null) throw new EntityException("The object could not be updated. Set the Context before attempting to update this object.");
            if (Command == null) Command = Context.CreateCommand();
            Command.Update(this);
        }

        public virtual void Select()
        {
            if (Context == null) throw new EntityException("The object could not be selected. Set the Context before attempting to select this object.");
            if (Command == null) Command = Context.CreateCommand();
            if (Concurrency == null) Concurrency = Context.CreateConcurrency();
            Command.Select(this);
        }

        public virtual void Insert()
        {
            if (Context == null) throw new EntityException("The object could not be inserted. Set the Context before attempting to insert for this object.");
            if (Command == null) Command = Context.CreateCommand();
            Command.Insert(this);
        }

        public virtual void Delete(DeleteMode deleteMode)
        {
            if (Context == null) throw new EntityException("The object could not be deleted. Set the Context before attempting to delete this object.");
            if (Command == null) Command = Context.CreateCommand();
            Command.Delete(this, deleteMode);
        }

        public virtual bool Exists()
        {
            if (Context == null) throw new EntityException("The object could not be checked. Set the Context before attempting to check this object.");
            if (Command == null) Command = Context.CreateCommand();
            return Command.Exists(this);
        }

        #endregion
    }
}